﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace AgvPublic
{
    public delegate void AgvInfoTcpDelegate(string ip, byte[] buffer);
    public delegate void CallBoxTcpDelegate(string ip);
    public delegate void LampTcpDelegate(byte[] buffer);//电梯委托

    public class TcpServer
    {

        public event AgvInfoTcpDelegate AgvInfoTcpEvent;
        public event CallBoxTcpDelegate CallBoxConnectEvent;
        public event AgvInfoTcpDelegate CallBoxDataEvent;
        public event AgvInfoTcpDelegate FloorChargeTcpEvent;
        public event LampTcpDelegate LampTcpEvent;

        public const int BufferSize = 1024;
       
        public byte[] bufferCallBox = new byte[BufferSize];
        public byte[] bufferFloorCharge = new byte[BufferSize];
        public byte[] bufferSinal = new byte[BufferSize];

       

        #region Fields
        /// <summary>
        /// 服务器程序允许的最大客户端连接数
        /// </summary>
        private int _maxClient;
 
        /// <summary>
        /// 当前的连接的客户端数
        /// </summary>
        private int _clientCount;
 
        /// <summary>
        /// 服务器使用的异步socket
        /// </summary>
        private Socket _serverSock;
 
        /// <summary>
        /// 客户端会话列表
        /// </summary>
        public List<Socket> _clients;
 
        private bool disposed = false;
 
        #endregion
 
        #region Properties
 
        /// <summary>
        /// 服务器是否正在运行
        /// </summary>
        public bool IsRunning { get; private set; }
        /// <summary>
        /// 监听的IP地址
        /// </summary>
        public IPAddress Address { get; private set; }
        /// <summary>
        /// 监听的端口
        /// </summary>
        public int Port { get; private set; }
        /// <summary>
        /// 通信使用的编码
        /// </summary>
        public Encoding Encoding { get; set; }

        Dictionary<string, byte[]> bufferDic=new Dictionary<string,byte[]>();
        #endregion
 
        #region Ctors
 
        /// <summary>
        /// 异步Socket TCP服务器
        /// </summary>
        /// <param name="localIPAddress">监听的IP地址</param>
        /// <param name="listenPort">监听的端口</param>
        /// <param name="maxClient">最大客户端数量</param>
        public TcpServer(Dictionary<string, byte[]> tempDic)
        {
            bufferDic = tempDic;

            this.Address = IPAddress.Any;
            this.Port = 8080;
            this.Encoding = Encoding.Default;
 
            //_maxClient = maxClient;
            _clients = new List<Socket>();
            _serverSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }


        public bool IsSocketConnected(Socket s)
        {
            bool c = false;
            if (s != null && s.Connected)
            {
                c= !((s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)) || !s.Connected);
            }
            return c;          
        }
        #endregion
 
        #region Server
 
        /// <summary>
        /// 启动服务器
        /// </summary>
        /// <returns>异步TCP服务器</returns>
        public TcpServer Start()
        {
            if (!IsRunning)
            {
                IsRunning = true;
                _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                _serverSock.Listen(1024);
                _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
                //log.Warn("服务器启动");
            }
            return this;
        }
 
        /// <summary>
        /// 启动服务器
        /// </summary>
        /// <param name="backlog">
        /// 服务器所允许的挂起连接序列的最大长度
        /// </param>
        /// <returns>异步TCP服务器</returns>
        public TcpServer Start(int backlog)
        {
            if (!IsRunning)
            {
                IsRunning = true;
                _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
                _serverSock.Listen(backlog);
                _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);
            }
            return this;
        }
 
        /// <summary>
        /// 停止服务器
        /// </summary>
        /// <returns>异步TCP服务器</returns>
        public TcpServer Stop()
        {
            if (IsRunning)
            {
                IsRunning = false;
                _serverSock.Close();
                //TODO 关闭对所有客户端的连接
 
            }
            return this;
        }
        #endregion
 
        #region Receive
        /// <summary>
        /// 处理客户端连接
        /// </summary>
        /// <param name="ar"></param>
        private void HandleAcceptConnected(IAsyncResult ar)
        {
            Socket server = (Socket)ar.AsyncState;                
            try
            {                
                Socket client = server.EndAccept(ar);
                
                //检查是否达到最大的允许的客户端数目
                string ip = client.RemoteEndPoint.ToString().Split(':')[0];

                if (_clients.Count > 0)
                {
                    for (int i = 0; i < _clients.Count; i++)
                    {
                        if (_clients[i].RemoteEndPoint.ToString().Split(':')[0] == ip)
                        {
                            try
                            {
                                this.CloseClient(_clients[i]);
                            }
                            catch
                            { }
                            
                        }
                    }

               
                    _clients.Add(client);
                   
                }
                else
                {
                    _clients.Add(client);
                }
             
               
               
                if (bufferDic.ContainsKey(ip))
                {
                    client.BeginReceive(bufferDic[ip], 0, bufferDic[ip].Length, SocketFlags.None,
                                       new AsyncCallback(HandleDataReceived), client);
                }

             
                //接受下一个请求                            
                 server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);
                   
            }
            catch (SocketException ex)
            {
                server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);
                //log.Error("HandleAcceptConnected" + ex.Message);
            }
            catch (ObjectDisposedException ex)
            {
                server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);
                //log.Error("HandleAcceptConnected" + ex.Message);
                //System.Diagnostics.Trace.WriteLine("TCPAsyncServer无法访问已经释放对象的监听服务....");
            }

        }
        /// <summary>
        /// 处理客户端数据
        /// </summary>
        /// <param name="ar"></param>
        private void HandleDataReceived(IAsyncResult ar)
        {                  
                try
                {
                    Socket client = (Socket)ar.AsyncState;
                    if (client != null && client.Connected)
                    {
                        int recv = client.EndReceive(ar);
                        if (recv > 0)
                        {
                            string ip = client.RemoteEndPoint.ToString().Split(':')[0];

                            if (bufferDic.ContainsKey(ip))
                            {
                                AgvInfoTcpEvent(ip, bufferDic[ip]);
                                client.BeginReceive(bufferDic[ip], 0, bufferDic[ip].Length, SocketFlags.None,
                               new AsyncCallback(HandleDataReceived), client);
                            }

                          
                        }                                                      
                    }
                       
                }
                catch (SocketException ex)
                {
                    //log.Error("HandleDataReceived" + ex.Message);
                    return;
                }
                catch (ObjectDisposedException ex)
                {
                    //log.Error("HandleDataReceived" + ex.Message);
                    return;
                }
        }
        #endregion
 
        #region Send
       
        /// <summary>
        /// 异步发送数据至指定的客户端
        /// </summary>
        /// <param name="client">客户端</param>
        /// <param name="data">报文</param>
        public void Send(Socket client, byte[] data)
        {
            if (!IsRunning)
                throw new InvalidProgramException("This TCP Scoket server has not been started.");
 
            if (client == null)
                throw new ArgumentNullException("client");
 
            if (data == null)
                throw new ArgumentNullException("data");
            try
            {
                if (client != null && client.Connected)
                {
                    client.BeginSend(data, 0, data.Length, SocketFlags.None,
                            new AsyncCallback(SendDataEnd), client);
                }
               
            }
            catch (SocketException ex)
            {
                //log.Error("Send" + ex.Message);
            }
            catch (ObjectDisposedException ex)
            {
                //log.Error("Send" + ex.Message);
            }
         
        }
 
        /// <summary>
        /// 发送数据完成处理函数
        /// </summary>
        /// <param name="ar">目标客户端Socket</param>
        private void SendDataEnd(IAsyncResult ar)
        {
            ((Socket)ar.AsyncState).EndSend(ar);
        }
        #endregion
  
        #region Close
        /// <summary>
        /// 关闭一个与客户端之间的会话
        /// </summary>
        /// <param name="closeClient">需要关闭的客户端会话对象</param>
        public void CloseClient(Socket _client)
        {
            try
            {
                _clients.Remove(_client);
                //关闭数据的接受和发送
                _client.Shutdown(SocketShutdown.Both);

                //清理资源
                _client.Close();

            }
            catch (Exception ex)
            {
                //log.Error("CloseClient" + ex.Message);
            }
        }
        /// <summary>
        /// 关闭所有的客户端会话,与所有的客户端连接会断开
        /// </summary>
        public void CloseAllClient()
        {
            foreach (Socket client in _clients)
            {
                CloseClient(client);
            }
            _clientCount = 0;
            _clients.Clear();
        }
 
      
        #endregion   
    }
}
